#include "cmd_centre.h"
#include "cmd_reader.h"

using namespace vpm::cmo;


CmdReader::CmdReader()
{	m_cmdView = CmdCentre::instance().get_view();
	m_cmdUserSession = CmdCentre::instance().acquire_user_session(m_cmdView);
	m_bRunning = true; 
}

CmdReader::~CmdReader()
{
	CmdCentre::instance().release_user_session(m_cmdUserSession);
}

void CmdReader::read()
{
	char ch ; 
	while (m_bRunning)
	{
		if (m_cmdUserSession->is_login())
		{			
			ch = read_char();
			this->process_char(ch);
		}
		else 
		{
			std::string user, pass;
			bool rst = true; 
			do 
			{						
				user = this->read_user();
				pass = this->read_password();		
				rst = m_cmdUserSession->login(user,pass);
				if (!rst)
				{
					write_string("login failed \r\n");
				}
			}while (!rst && m_bRunning);
			write_string("login success \r\n");
			write_string(m_cmdUserSession->cmd_view()->view_prompt().c_str());
		}
	}
}

std::string CmdReader::read_user()
{
	static const std::string loginPrompt = "login:";
	char ch;
	int pos = 0; 
	char tmpBuf[512]; 				
	write_string(loginPrompt.c_str());
	while(m_bRunning)
	{					
		if ((unsigned int)pos >= sizeof(tmpBuf))
		{
			break; 
		}
		ch = read_char(); 
		if (ch == 0 )
		{
			m_bRunning= false; 
			break;
		}

		if (ch < 0 || ch=='\t' || ch==' ')
		{
			continue;
		}

		if (isprint(ch))
		{
			tmpBuf[pos++] = ch; 
			write_char(ch);
		}
		else if (ch == '\b')
		{
			if (pos > 0)
			{				
				tmpBuf[pos--] = 0;
				write_string("\b \b");
			}
		}
		else
		{
			write_string("\r\n");			
			tmpBuf[pos] = 0;

			if (pos > 0)
			{
				return std::string(tmpBuf);
			}
			else 
			{
				write_string(loginPrompt.c_str());
			}
		}
	}
	return std::string();
}		

std::string CmdReader::read_password()
{	
	static const std::string passwordPrompt = "password:";							
	char ch ; 
	int pos = 0; 	
	char tmpBuf[512]= {0}; 
	write_string(passwordPrompt.c_str());
	while(m_bRunning)
	{
		if ((unsigned int)pos >= sizeof(tmpBuf))
		{
			break; 
		}
		ch = read_char(); 		
		if (ch == 0 )
		{
			m_bRunning= false; 
			break;
		}

		if (ch < 0 || ch=='\t')
		{
			continue;
		}

		if (isprint(ch))
		{
			tmpBuf[pos++] = ch; 
			write_char('*');
		}
		else if (ch == '\b')
		{
			tmpBuf[pos--] = 0;
			std::cout <<"\b \b";
		}
		else
		{
			write_string("\r\n");
			tmpBuf[pos] = 0;					
			if (pos >= 0 )
			{
				return std::string (tmpBuf);
			}
			else
			{
				write_string(passwordPrompt.c_str());
			}
		}
	}	
	return std::string();
}


void CmdReader::process_char(char ch)
{
	if (ch <= 0)
	{
		return; 
	}

	if (iscntrl(ch))
	{
		m_cmdUserSession->control_action(ch);
#ifdef WIN32 
		if (ch = '\n')
		{
			write_string("\r\n");
		}
#endif // 
		
		write_string(m_cmdUserSession->cmd_view()->view_prompt().c_str());
	}
	else if (isspace(ch) )
	/*  checks  for  white-space  characters.   In  the "C" and "POSIX" locales, these are: space, form-feed ('\f'), newline ('\n'), carriage return
	('\r'), horizontal tab ('\t'), and vertical tab ('\v'). 	*/
	{
		if (ch == '\t')
		{
			m_cmdUserSession->tab_action();
		}
		else 
		{
			m_cmdUserSession->space_action();
		}		
	}	
	else 
	{
		m_cmdUserSession->nonspace_action(ch);
	}
}
 
